// **************************************************************************
// Desc:
// **************************************************************************

Components.utils.import("resource://gre/modules/Services.jsm");

var OpenidNascarProgressListener = {
	QueryInterface : function(aIID) {
		if (aIID.equals(Components.interfaces.nsIWebProgressListener)
				|| aIID.equals(Components.interfaces.nsISupportsWeakReference)
				|| aIID.equals(Components.interfaces.nsISupports)) {
			return (this);
		}

		throw Components.results.NS_NOINTERFACE;
	},

	onStateChange : function(aProgress, aRequest, aFlag, aStatus) {
		var progListIFace = Components.interfaces.nsIWebProgressListener;

		// Log the flags

		// Process the document. The 'STOP' state isn't reached until after
		// the page is fully loaded and all onload events have completed.
		// We need to re-process the page in case an onload event added
		// information card elements or objects to the page. An example of
		// a page that does this is login.live.com.

		if (aFlag & progListIFace.STATE_STOP) {
			if ((aFlag & progListIFace.STATE_IS_WINDOW) || (aFlag & progListIFace.STATE_IS_DOCUMENT)) {
				if (aStatus === 0) {
					try {
						var channel = aRequest.QueryInterface(Components.interfaces.nsIChannel);
						if (channel != Components.results.NS_NOINTERFACE) {
//							Application.console.log("OpenidNascarProgressListener onStateChange channel.contentType=" +
//									channel.contentType);
							if ("application/json" == channel.contentType) {
								
							}
						} else {
//							Application.console.log("OpenidNascarProgressListener onStateChange: no channel");
						}
//						var doc = aProgress.DOMWindow.document;
//						var documentElement = doc.documentElement;
//						Application.console.log("OpenidNascarProgressListener onStateChange documentElement=" + documentElement);
//						var domSerializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
//	                    	.createInstance(Components.interfaces.nsIDOMSerializer);
//						var stringContent = domSerializer.serializeToString(documentElement);
//						Application.console.log("OpenidNascarProgressListener onStateChange stringContent=" + stringContent);
//						var name = aRequest.name;
//						Application.console.log("OpenidNascarProgressListener onStateChange name=" + name);
					} catch (e) {
						Application.console.log("OpenidNascarProgressListener onStateChange " + e);
					}
				}
			}
		}

		return (0);
	},

	onLocationChange : function(aProgress, aRequest, aURI) {
		// This fires when a load event has been confirmed or when the
		// user switches tabs. At this point, Firefox has created a skeletal
		// document into which the source document will be loaded. This is
		// where we run our global intercept script.

		try {

		} catch (e) {
			Application.console.log("onLocationChange:" + e);
		}

		return (0);
	},

	onProgressChange : function() {
		return (0);
	},

	onStatusChange : function() {
		return (0);
	},

	onSecurityChange : function() {
		return (0);
	},

	onLinkIconAvailable : function() {
		return (0);
	}
};

var OpenIdNascar = {
	consoleService : null,

	_logMessage : function _logMessage(message) {
		if (!OpenIdNascar.consoleService) {
			OpenIdNascar.consoleService = Services.console;
		}
		//OpenIdNascar.consoleService.logStringMessage("OpenIdNascar:" + message);
	},

	store : function _store(realm, claimed_id, identity, op_endpoint) {
//		OpenIdNascar._logMessage("store: claimed_id=" + claimed_id);
		try {
			var OpenIdStorage = Components.classes['@openinfocard.com/openidstorage;1']
					.getService().wrappedJSObject;
			OpenIdStorage.addOpenID(realm, claimed_id, identity, op_endpoint);
			var preferredOpenidProvider = OpenIdStorage.getPreferredOpenID();
//			OpenIdNascar._logMessage("store preferredOpenidProvider="
//					+ preferredOpenidProvider);
			if (!preferredOpenidProvider) {
				OpenIdStorage.setPreferredOpenID(claimed_id, identity,
						op_endpoint);
			}
			try {
			  var popupImage = document.getElementById("openid-nascar-popup-image")
	      if (popupImage) {
	        var imageSrc = popupImage.src;
	        if (imageSrc) {
	          OpenIdNascar._logMessage("store: imageSrc=" + imageSrc);
	          Components.utils.import("resource://openidnascar/image.jsm");
	          storeOpenIdImage(OpenIdStorage, realm, claimed_id, popupImage, null);
	        }
	      }
			} catch (ex) {
			  Components.utils.reportError(e);
	    }
    } catch (ex) {
      Components.utils.reportError(e);
    }
  },

  popupImageLoad : function _popupImageLoad() {
    try {
      OpenIdNascar._logMessage("popupImageLoad");
    } catch (ex) {
      Components.utils.reportError(e);
    }
  },

  popupImageError : function _popupImageError() {
    try {
      OpenIdNascar._logMessage("popupImageError");
      var popupImage = document.getElementById("openid-nascar-popup-image")
      if (popupImage) {
        popupImage.setAttribute("src", "chrome://openidnascar/content/openid-icon-100x100.png");
      } else {
        Components.utils.reportError("popupImageError internal error: popup image not found");
      }
    } catch (e) {
      Components.utils.reportError(e);
    }
	},
	
	popupNotification : function _popupNotification(realm, claimed_id,
			identity, op_endpoint) {
		var self = this;
		var tmp = {};
		var pop;
		try {
//			OpenIdNascar._logMessage("PopupNotification realm=" + realm);
//			OpenIdNascar._logMessage("PopupNotification claimed_id="
//					+ claimed_id);
			Components.utils.import(
					"resource://gre/modules/PopupNotifications.jsm", tmp);
			pop = new tmp.PopupNotifications(gBrowser, document
					.getElementById("notification-popup"), document
					.getElementById("notification-popup-box"));
    } catch (ee) {
      Components.utils.reportError(ee);
      return;
    }

    
    try {
      var popupImage = document.getElementById("openid-nascar-popup-image")
      if (popupImage) {
//        popupImage.addEventListener("error", OpenIdNascar.popupImageError, true);
        popupImage.onerror = OpenIdNascar.popupImageError;
//        popupImage.onload = OpenIdNascar.popupImageLoad;
        var pageSpec = unescape(claimed_id);
        var pageUri = Services.io.newURI(pageSpec, null, null);
        pageSpec = pageUri.prePath + "/favicon.ico";
        OpenIdNascar._logMessage("PopupNotification popup-image src=" + pageSpec);
        popupImage.setAttribute("src", pageSpec);
      } else {
        Components.utils.reportError("internal error: popup image not found");
      }
    } catch (e) {
      Components.utils.reportError(e);
      return;
    }

    
    try {
			var anchorId = "openid-nascar-url-bar-image";
			var options = {
				timeout : Date.now() + 30000
			};
			var bundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
					.getService(Components.interfaces.nsIStringBundleService);
			var browserBundle = bundleService
					.createBundle("chrome://openidnascar/locale/openid.properties");
			var message = browserBundle.formatStringFromName("openid.savethis",
					[ unescape(claimed_id) ], 1);
			var label = browserBundle.GetStringFromName("openid.savethislabel");
			return pop.show(gBrowser.selectedBrowser,
					"org-openinfocard-openid", message, anchorId, {
						label : label,
						accessKey : "S",
						callback : function() {
							self
									.store(realm, claimed_id, identity,
											op_endpoint);
						}
					}, null, /* secondary action */
					options);
		} catch (ex) {
			OpenIdNascar._logMessage("popupNotification Exception" + ex);
			return;
		}
	},

	// <link rel="openid2.provider openid.server"
	// href="https://www.startssl.com/id.ssl" />
	// <link rel="openid2.local_id openid.delegate"
	// href="https://www.startssl.com/" />
	processLinkElements : function _processLinkElements(doc) {
		var headElts = doc.getElementsByTagName("head");
		if (!headElts)
			return;
		if (headElts.lenght != 1)
			return;
		var linkElts = headElts[0].getElementsByTagName("link");
		var op;
		for ( var i = 0; i < linkElts.length; i++) {
			var linkElt = linkElts.item(i);
			var rel = linkElt.getAttribute("rel");
			if (rel) {
				if (rel.indexOf("openid2.provider") > -1) {
					var href = linkElt.getAttribute("href");
					if (href) {
						op = href;
						break;
					}
				}
				if (rel.indexOf("openid.server") > -1) {
					var href = linkElt.getAttribute("href");
					op = href;
					break;
				}
			}
		}
		if (op) {
			// ask user to store this openid provider
			// FIXME
		}
	},

	openidfieldhandler : function _openidfieldhandler(doc, mainWindow) {
//		OpenIdNascar._logMessage("openidfieldhandler doc.location.href="
//				+ doc.location.href);
		var icon = mainWindow.document
				.getElementById("openid-nascar-url-bar-image");
		if (!icon) {
			return;
		}
		Components.utils.import("resource://openidnascar/inputfields.jsm");
		var inputField = findBestInputField(doc, OpenIdNascarUrlbar._logMessage);
		if (inputField) {
//			OpenIdNascar._logMessage("openidfieldhandler inputField.name="
//					+ inputField.name);
			icon.setAttribute("src",
					"chrome://openidnascar/content/openid-16x16-checked.gif");
		} else {
//			OpenIdNascar._logMessage("openidfieldhandler no inputField");
			icon.setAttribute("src",
					"chrome://openidnascar/content/openid-16x16.gif");
		}
	},

	onDOMContentLoaded : function _onDOMContentLoaded(event) {
		if (!(event.originalTarget instanceof HTMLDocument)) {
//			OpenIdNascar._logMessage("onDOMContentLoaded: is no HTMLDocument");
			return;
		}

		var doc = event.originalTarget;
//		OpenIdNascar._logMessage("onDOMContentLoaded start doc.location.href="
//				+ doc.location.href);

		let
		docRoot = doc.documentElement;
		if (docRoot.hasAttribute("privatebrowsingmode")) {
			return; // Private browsing mode is enabled
		}

		var win = doc.defaultView;
		var mainWindow = win.QueryInterface(
				Components.interfaces.nsIInterfaceRequestor).getInterface(
				Components.interfaces.nsIWebNavigation).QueryInterface(
				Components.interfaces.nsIDocShellTreeItem).rootTreeItem
				.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
				.getInterface(Components.interfaces.nsIDOMWindow);

		win.setTimeout(OpenIdNascar.openidfieldhandler, 100, doc, mainWindow);

		if (mainWindow.__openid__) {
			OpenIdNascar
					._logMessage("onDOMContentLoaded mainWindow.__openid__.realm="
							+ mainWindow.__openid__.realm);
			OpenIdNascar
					._logMessage("onDOMContentLoaded mainWindow.__openid__.claimed_id="
							+ mainWindow.__openid__.claimed_id);
			OpenIdNascar
					._logMessage("onDOMContentLoaded mainWindow.__openid__.identity="
							+ mainWindow.__openid__.identity);
			OpenIdNascar
					._logMessage("onDOMContentLoaded mainWindow.__openid__.op_endpoint="
							+ mainWindow.__openid__.op_endpoint);

			try {
				if (!mainWindow.__openid__.claimed_id) {
					OpenIdNascar
							._logMessage("onDOMContentLoaded !mainWindow.__openid__.claimed_id");
					return;
				}
				var OpenIdStorage = Components.classes['@openinfocard.com/openidstorage;1']
						.getService().wrappedJSObject;
				if (!OpenIdStorage
						.isOpenIdInStore(mainWindow.__openid__.claimed_id)) {
					var realm = mainWindow.__openid__.realm;
					if (!realm) {
						var iOService = Components.classes["@mozilla.org/network/io-service;1"]
								.getService(Components.interfaces.nsIIOService);
						var realmUri = iOService.newURI(doc.location.href,
								null, null);
						realm = realmUri.prePath;
//						OpenIdNascar._logMessage("onDOMContentLoaded : realm="
//								+ realm);
					} else {
						realm = unescape(realm);
					}
					var popup = OpenIdNascar.popupNotification(realm,
							mainWindow.__openid__.claimed_id,
							mainWindow.__openid__.identity,
							mainWindow.__openid__.op_endpoint);
				} else {
					OpenIdNascar
							._logMessage("onDOMContentLoaded : is already in store="
									+ mainWindow.__openid__.claimed_id);
				}
			} catch (eee) {
				OpenIdNascar._logMessage("onDOMContentLoaded Exception=" + eee);
			} finally {
				try {
					mainWindow.__openid__ = null;
					delete mainWindow.__openid__;
				} catch (e) {
				}
			}
		}
//		OpenIdNascar._logMessage("onDOMContentLoaded doc.location.href="
//				+ doc.location.href);
	},

	onInstall : function _onInstall(event) {
//		OpenIdNascar._logMessage("onInstall");
		window.removeEventListener("load", OpenIdNascar.onInstall);
		var win = event.originalTarget;
		win.addEventListener("DOMContentLoaded",
				OpenIdNascar.onDOMContentLoaded, false, true);
		window.getBrowser().addProgressListener(OpenidNascarProgressListener);
	},

	onUninstall : function _onUninstall(event) {
		window.getBrowser().removeProgressListener(OpenidNascarProgressListener);
		window.removeEventListener("unload", OpenIdNascar.onUninstall);
	}
};

// **************************************************************************
// Desc: Startup and shutdown
// **************************************************************************

try {
//	OpenIdNascar._logMessage("Start");
	window.addEventListener("load", OpenIdNascar.onInstall, false);
	
	window.addEventListener("unload", OpenIdNascar.onUninstall, false);
} catch (e) {
	window.alert("window.addEventListener " + e);
	OpenIdNascar._logMessage("exception: " + e);
}